﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using LeanEngine.Extensions;

namespace LeanEngine.Business
{
    public abstract class BusinessWorkflow<TParam, TResult> : IBusinessWorkflow
        where TParam : class
        where TResult : class
    {
        #region Method Members

        public TResult Execute(TParam value)
        {
            var processingResult = ExecuteWorkFlow(value);

            if (this.ExecutionCounter.IsNotNull())
            {
                this.ExecutionCounter.Increment();
            }

            return processingResult;
        }

        #endregion

        #region Abstract Members

        protected abstract TResult ExecuteWorkFlow(TParam value);

        #endregion

        #region IBusinessWorkflow Members

        /// <summary>
        /// Gets the execution performance counter category
        /// </summary>
        public abstract DiagnosticCategoryItem ExecutionCounter
        {
            get;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns>Returns null.</returns>
        public object Execute(object value)
        {
            var tParamValue = value as TParam;
            if (tParamValue == null) throw new ArgumentOutOfRangeException("value", value, "The value must be of " + typeof(TParam).FullName + " data type.");

            return this.Execute(value as TParam);
        }

        #endregion
    }

    public abstract class BusinessWorkflow<TParam> : IBusinessWorkflow
        where TParam : class
    {
        #region Method Members

        public void Execute(TParam value)
        {
            ExecuteWorkFlow(value);

            if (this.ExecutionCounter.IsNotNull())
            {
                this.ExecutionCounter.Increment();
            }
        }

        #endregion

        #region Abstract Members

        protected abstract void ExecuteWorkFlow(TParam value);

        #endregion

        #region IBusinessWorkflow Members

        /// <summary>
        /// Gets the execution performance counter category
        /// </summary>
        public abstract DiagnosticCategoryItem ExecutionCounter
        {
            get;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns>Returns null.</returns>
        public object Execute(object value)
        {
            var tParamValue = value as TParam;
            if (tParamValue == null) throw new ArgumentOutOfRangeException("value", value, "The value must be of " + typeof(TParam).FullName + " data type.");

            this.Execute(value as TParam);
            
            return null;
        }

        #endregion
    }

    public interface IBusinessWorkflow
    {
        /// <summary>
        /// Gets the execution performance counter category
        /// </summary>
        DiagnosticCategoryItem ExecutionCounter { get; }

        object Execute(object value);
    }
}
